#include "damfCG2009.h"


int damfCG2009::dif(int vIni, int vFim){
	return vFim - vIni;
};

int damfCG2009::round(double numero){
	int retorno = 0;
	double downRound = floor(numero);
	if(numero >= (downRound + 0.5)){
		retorno = ceil(numero);
	}else{
		retorno = downRound;
	}
	return retorno;
};

void damfCG2009::retaPontoMedio(double x1, double y1, double x2, double y2)
{
	double Xpini;
	double Xpfim;
	double Ypini;
	double Ypfim;
	double m,B,b,a,c;
	double drawX;
	double drawY;
	double increm1;
	double increm2;
	double dstart;

	if (x1 == x2 ){
		if (y1 < y2){
			for (drawY = y1; drawY <= y2; drawY ++){
				this->myPixel(x1, drawY);
			}
		}else{
			for (drawY = y2; drawY <= y1; drawY ++){
				this->myPixel(x1, drawY);
			}
		}
	}
	else if (y1 == y2 )
	{
		if (x1 < x2){
			for (drawX = x1; drawX <= x2; drawX ++){
				this->myPixel(drawX, y1);
			}
		}else{
			for (drawX = x2; drawX <= x1; drawX ++){
				this->myPixel(drawX, y2);
			}
		}
	}else{
		if (y1 > y2){
			Xpfim = x1;
			Ypfim = y1;
			Xpini = x2;
			Ypini = y2;
		}else{
			Xpfim = x2;
			Ypfim = y2;
			Xpini = x1;
			Ypini = y1;
		}

		m = (Ypfim - Ypini)/(Xpfim - Xpini);
		B = Ypfim - m*Xpfim;
		a = (Ypfim - Ypini);
		b = (Xpfim - Xpini)*(-1);
		c = B*(Xpfim - Xpini);

		if ( m == 1 ){
			drawY = Ypini ;
			for (drawX = Xpini; drawX <= Xpfim; drawX ++){                
				this->myPixel(drawX, drawY);
				drawY ++;
			}            
		}else if (m == - 1){
			drawY = Ypini ;
			for (drawX = Xpini; drawX >= Xpfim; drawX --){                
				this->myPixel(drawX, drawY);
				drawY ++;
			}
		}else if (m > 1 ){
			dstart = a+2*b;
			increm1 = 2*b;
			increm2 = 2*(a+b);

			drawX = Xpini;
			drawY = Ypini;

			this->myPixel(drawX, drawY);

			if (dstart < 0 ){
				drawX++;    
			}

			drawY++;
			this->myPixel(drawX, drawY);

			do{
				if (dstart >=0){
					dstart = dstart + increm1;
				}else{
					dstart = dstart + increm2;
				}

				if (dstart <0){
					drawX++;
				}

				drawY ++;

				this->myPixel(drawX, drawY);
			}while (drawY < Ypfim);

		}else if (m < 1 && m > 0){
			increm1 = 2*a;
			increm2 = 2*a + 2*b;
			dstart = 2*a + b;

			drawX = Xpini;
			drawY = Ypini;
			this->myPixel(drawX, drawY);

			if (dstart >= 0){
				drawY++;
			}

			drawX++;
			this->myPixel(drawX, drawY);

			do{
				if (dstart >=0){
					dstart = dstart + increm2;
				}else{
					dstart = dstart + increm1;
				}

				if (dstart >=0){
					drawY++;
				}

				drawX++;

				this->myPixel(drawX, drawY);
			}while (drawX < Xpfim);   
		}else if (m < -1){
			increm1 = 2*b;
			increm2 = 2*b - 2*a;
			dstart = 2*b - a;

			drawX = Xpini;
			drawY = Ypini;
			this->myPixel(drawX, drawY);

			if (dstart >=0){
				drawX --;
			}

			drawY ++;
			this->myPixel(drawX, drawY);

			do{
				if (dstart >=0){
					dstart = dstart + increm2;
				}else{
					dstart = dstart + increm1;
				}

				if (dstart >=0){
					drawX--;
				}

				drawY++;
				this->myPixel(drawX, drawY);

			}while (drawY < Ypfim);
		}else if (m >-1 && m <0){
			increm1 = 2*a*(-1);
			increm2 = 2*b - 2*a;
			dstart = b - 2*a;

			drawX = Xpini;
			drawY = Ypini;
			this->myPixel(drawX, drawY);

			if (dstart < 0){
				drawY++;
			}

			drawX--;
			this->myPixel(drawX, drawY);

			do{
				if (dstart < 0){
					dstart = dstart + increm2;
				}else{
					dstart = dstart + increm1;
				}

				if (dstart < 0){
					drawY ++;
				}

				drawX--;
				this->myPixel(drawX, drawY);
			}while (drawX > Xpfim);       
		}
	}     
}

void damfCG2009::calculaSegundoOctante(int x1,int y1,int x2, int y2, double dx, double dy){
	double ince, incne, d, a, b;
	a = dy;
	b = -1 * dx;

	ince = 2*a;
	incne = 2*(a+b);

	d = 2*a+b;

	this->myPixel(x1, y1);
	do{
		if(d > 0){
			x1 += 1;
			y1 += 1;
			d += incne;
		}else{
			x1 += 1;
			d += ince;
		}
		this->myPixel(x1, y1);
	}while(x1 != x2 || y1 != y2);
};

void damfCG2009::drawLineDDA(int x1, int y1, int x2, int y2){
	int dx, dy, steps;
	double incx, incy, x = x1, y  = y1;

	dx = this->dif(x1, x2);
	dy = this->dif(y1, y2);

	if (abs(dx) > abs(dy)){
		steps = abs(dx);
	}else{
		steps = abs(dy);
	}

	incx = (double)dx/steps;
	incy = (double)dy/steps;

	x = x1;
	y = y1;

	this->myPixel(round(x), round(y));
	for(int k = 0; k < steps; k++){
		x += incx;
		y += incy;
		this->myPixel(round(x), round(y));
	}
};


void damfCG2009::myPixel(int x, int y){
	double tam = 1;
	x = x*tam;
	y = y*tam;
	if(!this->_centralizado){
		glVertex2f(x, y);
		glVertex2f(x + tam, y);
		glVertex2f(x + tam, y + tam);
		glVertex2f(x, y + tam);
	}else{
		glVertex2f(x - 0.5, y - 0.5);
		glVertex2f(x - 0.5 + tam, y - 0.5);
		glVertex2f(x - 0.5 + tam, y - 0.5 + tam);
		glVertex2f(x - 0.5, y - 0.5 + tam);
	}
};

void damfCG2009::desenharRetaXfixoYvariando (double Xpini, double Ypini, double Xpfim, double Ypfim ){
	double m;
	double b;
	double parada;
	double inicio;
	double drawX;
	double drawY;

	if (Xpfim == Xpini ){
		if (Ypini < Ypfim){
			for (drawY = Ypini; drawY < Ypfim; drawY ++){
				this->myPixel(Xpfim, drawY);
			}

		}else{
			for (drawY = Ypfim; drawY < Ypini; drawY ++){
				this->myPixel(Xpfim, drawY);
			}
		}
	}
	else if (Ypfim == Ypini ){
		if (Xpini < Xpfim){
			for (drawX = Xpini; drawX < Xpfim; drawX ++){
				this->myPixel(drawX, Ypfim);
			}
		}else{
			for (drawX = Xpfim; drawX < Xpini; drawX ++){
				this->myPixel(drawX, Ypfim);
			}
		}
	}else {
		m = (Ypfim - Ypini)/(Xpfim - Xpini);
		b = Ypini - (m*Xpini);

		if (Xpini <  Xpfim){
			inicio = Xpini;
			parada = Xpfim;
		}else{
			inicio = Xpfim;
			parada = Xpini;
		}

		for (drawX=inicio; drawX<= parada; drawX++){
			drawY = m*drawX + b;

			if (drawY > floor(drawY) + 0.5){
				drawY = ceil(drawY);
			}else{
				drawY = floor(drawY);   
			}

			this->myPixel(drawX, drawY);
		}
	}
};

void damfCG2009::pontoCircuferencia(int x, int y){
	this->myPixel(x, y);
	this->myPixel(y, x);
	this->myPixel(y, -x);
	this->myPixel(x, -y);
	this->myPixel(-x, -y);
	this->myPixel(-y, -x);
	this->myPixel(-y,x);
	this->myPixel(-x, y);
};

void damfCG2009::pontoCircuferencia(int x, int y, int somaX, int somaY){
	this->myPixel(x + somaX, y + somaY);
	this->myPixel(y + somaX, x + somaY);
	this->myPixel(y + somaX, -x + somaY);
	this->myPixel(x + somaX, -y + somaY);
	this->myPixel(-x + somaX, -y + somaY);
	this->myPixel(-y + somaX, -x + somaY);
	this->myPixel(-y + somaX,x + somaY);
	this->myPixel(-x + somaX, y + somaY);
};

void damfCG2009::desenhaCircuferenciaPontoMedio(int x1, int y1, int x2, int y2){
	int x, y;
	float d;
	int raio = abs(x2 - x1);

	/* Valores iniciais */
	x = 0;
	y = raio;
	d = (double)5/4 - raio;
	this->pontoCircuferencia(x, y, x1, y1);
	while (y > x){
		if (d < 0){
			/* Selecione E */
			d = d + 2 * x + 3;
			x++;
		}else{
			/* Selecione SE */
			d = d + 2 * (x - y) + 5;
			x++;
			y--;
		}
		this->pontoCircuferencia(x, y, x1, y1);
	}
};

void damfCG2009::desenhaCircuferenciaExplicitaSimetrica(int x1, int y1, int x2, int y2){
	int x, y;
	float d;
	int raio = abs(x2 - x1);

	x = 0;
	y = raio;

	this->pontoCircuferencia(x, y, x1, y1);
	while(y > raio/sqrt(2.0)){
		y = this->round(sqrt(pow((float)raio, 2) - pow((float)x, 2)));
		x++;
		this->pontoCircuferencia(x, y, x1, y1);
	}
};

void damfCG2009::desenhaCircuferenciaExplicita(int x1, int y1, int x2, int y2){
	int x, y;
	float d;
	int raio = abs(x2 - x1);

	x = -raio;
	y = raio;

	//this->myPixel(x, y);

	while(y >= 0){
		y = this->round(sqrt(pow((float)raio, 2) - pow((float)x, 2)));
		x++;
		this->pontoCircuferencia(x, y, x1, y1);
		this->pontoCircuferencia(x, -y, x1, y1);
	}
};

void damfCG2009::setCentralizado(bool valor){
	this->_centralizado = valor;
};

bool damfCG2009::getCentralizado(){
	return this->_centralizado;
};
